#include "ComCtrlWidget.h"
#include "ui_ComCtrlWidget.h"

#include <QSerialPort>
#include <QSerialPortInfo>
#include <QMessageBox>
#include <QTimer>

ComCtrlWidget::ComCtrlWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ComCtrlWidget)
{
    ui->setupUi(this);

    p_serialPort = new QSerialPort();
    on_btnClose_clicked();

    QTimer::singleShot(100, this, [=]() {
        on_btnRefresh_clicked();
    });
}

ComCtrlWidget::~ComCtrlWidget()
{
    on_btnClose_clicked();
    p_serialPort->deleteLater();

    delete ui;
}

void ComCtrlWidget::openPort()
{
    QString dbg = "", tmp;

    //...set port name
    tmp = ui->cmbPortName->currentText();
    p_serialPort->setPortName(tmp);
    dbg += QString("PORT: %1\n").arg(tmp);

    //...
    if (!p_serialPort->open(QIODevice::ReadWrite)) {
        emit openPortFailed();

        QMessageBox::critical(this, "", tr("Open Failed"));
        return;
    }

    //...
    tmp = ui->cmbBaudRate->currentText();
    p_serialPort->setBaudRate(tmp.toInt(), QSerialPort::AllDirections);
    dbg += QString("RATE: %1\n").arg(tmp);
    //...
    switch (ui->cmbDataBits->currentText().toInt()) {
        case 5:
            dbg += QString("DBIT: %1\n").arg(5);
            p_serialPort->setDataBits(QSerialPort::Data5);
            break;
        case 6:
            dbg += QString("DBIT: %1\n").arg(6);
            p_serialPort->setDataBits(QSerialPort::Data6);
            break;
        case 7:
            dbg += QString("DBIT: %1\n").arg(7);
            p_serialPort->setDataBits(QSerialPort::Data7);
            break;
        case 8:
            dbg += QString("DBIT: %1\n").arg(8);
            p_serialPort->setDataBits(QSerialPort::Data8);
            break;
        default:
            dbg += QString("DBIT: %1\n").arg("ERROR");
            p_serialPort->setDataBits(QSerialPort::UnknownDataBits);
            break;
    }
    //...
    tmp = ui->cmbStopBits->currentText();
    dbg += QString("SBIT: %1\n").arg(tmp);
    switch (int(tmp.toDouble() * 10)) {
        case 10: p_serialPort->setStopBits(QSerialPort::OneStop); break; //一位停止位
        case 15: p_serialPort->setStopBits(QSerialPort::OneAndHalfStop); break;
        case 20: p_serialPort->setStopBits(QSerialPort::TwoStop); break;
        default: p_serialPort->setStopBits(QSerialPort::UnknownStopBits); break;
    }
    //...
    p_serialPort->setFlowControl(QSerialPort::NoFlowControl);
    //...
    tmp = ui->cmbParity->currentText();
    dbg += QString("PAR.: %1\n").arg(tmp);
    if ("NO" == tmp) {
        p_serialPort->setParity(QSerialPort::NoParity);	//无校验位
    } else if ("ODD" == tmp) {
        p_serialPort->setParity(QSerialPort::OddParity);
    } else if ("EVEN" == tmp) {
        p_serialPort->setParity(QSerialPort::EvenParity);
    } else if ("SPACE" == tmp) {
        p_serialPort->setParity(QSerialPort::SpaceParity);
    } else if ("MARK" == tmp) {
        p_serialPort->setParity(QSerialPort::MarkParity);
    }

    connect(p_serialPort,SIGNAL(readyRead()),this,SLOT(onReceiveData()));

    //...
    ui->btnClose->show();
    ui->btnOpen->hide();

    dbg += "---------------------------------\n\n";
    debugMessage(dbg.toUtf8());

    //...disable ui
    ui->cmbParity->setEnabled(false);
    ui->cmbBaudRate->setEnabled(false);
    ui->cmbDataBits->setEnabled(false);
    ui->cmbPortName->setEnabled(false);
    ui->cmbStopBits->setEnabled(false);
    ui->btnRefresh->setEnabled(false);

    emit openPortSuccess();
}

void ComCtrlWidget::closePort()
{
    if (p_serialPort->isOpen()) {
        p_serialPort->clear();
        p_serialPort->close();
    }

    disconnect(p_serialPort,SIGNAL(readyRead()),this,SLOT(onReceiveData()));

    ui->btnOpen->show();
    ui->btnClose->hide();
    //...enable ui
    ui->cmbParity->setEnabled(true);
    ui->cmbBaudRate->setEnabled(true);
    ui->cmbDataBits->setEnabled(true);
    ui->cmbPortName->setEnabled(true);
    ui->cmbStopBits->setEnabled(true);
    ui->btnRefresh->setEnabled(true);

    emit closePortSuccess();
}

void ComCtrlWidget::sendData(const QByteArray &data)
{
    if (p_serialPort && p_serialPort->isOpen()) {
        p_serialPort->write(data);
    }
}

void ComCtrlWidget::onReceiveData()
{
    QByteArray data = p_serialPort->readAll();
    emit dataReceived(data);
}

void ComCtrlWidget::on_btnRefresh_clicked()
{
    ui->cmbPortName->clear();

    const auto infos = QSerialPortInfo::availablePorts();
    for (auto info : infos) {
        ui->cmbPortName->addItem(info.portName());
    }
}

void ComCtrlWidget::on_btnOpen_clicked()
{
    openPort();
}

void ComCtrlWidget::on_btnClose_clicked()
{
    closePort();
}
